package com.liming.admin.aspect;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.liming.auth.client.AdminAuthClient;
import com.liming.common.anotation.AnyPermissionAuth;
import com.liming.common.anotation.AnyRoleAuth;
import com.liming.common.exception.BusinessException;
import com.liming.common.util.ThreadLocalUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.List;

import static com.liming.common.constant.SystemConstants.ID;

/**
 * @author liming
 * @date 2025/1/20
 */
@Slf4j
@Aspect
@Order(1)
@Component
@AllArgsConstructor
public class AuthAspect {

    private final AdminAuthClient adminAuthClient;

    private static boolean checkCollection(String adminId, HashSet<String> requirePermissions) {
        log.info("权限认证 - 管理员ID: {}", adminId);
        return CollUtil.isEmpty(requirePermissions);
    }

    private static void assertAuth(List<String> adminPermissions, String msg1, HashSet<String> requirePermissions, String msg2) {
        Assert.notEmpty(adminPermissions, () -> new BusinessException(msg1));
        Assert.isTrue(CollUtil.containsAny(adminPermissions, requirePermissions), () -> new BusinessException(msg2));
    }

    @Pointcut("execution(public * com.liming.admin.controller.*.*(..))")
    public void adminAuth() {
    }

    @Around("adminAuth() && @annotation(anyRoleAuth)")
    public Object anyRoleCheck(ProceedingJoinPoint proceedingJoinPoint, AnyRoleAuth anyRoleAuth) throws Throwable {
        String adminId = ThreadLocalUtils.get(ID);
        HashSet<String> requireRoles = CollUtil.newHashSet(anyRoleAuth.roles());
        if (checkCollection(adminId, requireRoles)) {
            return proceedingJoinPoint.proceed();
        }
        List<String> adminRoles = adminAuthClient.auth().getRoleList();
        assertAuth(adminRoles, "该管理员无角色分配 - 请联系超管分配角色", requireRoles, "管理员角色权限不够");
        return proceedingJoinPoint.proceed();
    }

    @Around("adminAuth() && @annotation(anyPermissionAuth)")
    public Object anyPermissionCheck(ProceedingJoinPoint proceedingJoinPoint, AnyPermissionAuth anyPermissionAuth) throws Throwable {
        String adminId = ThreadLocalUtils.get(ID);
        HashSet<String> requirePermissions = CollUtil.newHashSet(anyPermissionAuth.permissions());
        if (checkCollection(adminId, requirePermissions)) {
            return proceedingJoinPoint.proceed();
        }
        List<String> adminPermissions = adminAuthClient.auth().getPermissionList();
        assertAuth(adminPermissions, "管理员权限不存在", requirePermissions, "管理员权限不够");
        return proceedingJoinPoint.proceed();
    }

}
